<template>
  <!-- Live2D 模型展示容器 -->
  <div class="live2d-container">
    <!-- 模型画布 -->
    <canvas ref="canvasRef" class="live2d-canvas"></canvas>
    <!-- 加载/错误提示 -->
    <div v-if="isLoading" class="live2d-loading">模型加载中...</div>
    <div v-if="loadError" class="live2d-error">{{ loadError }}</div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue'
import { ElMessage } from 'element-plus'
import * as PIXI from 'pixi.js'
import { Live2DModel } from 'pixi-live2d-display/cubism4'

// ✅ 全局注册 Ticker，避免 "No Ticker registered" 报错
Live2DModel.registerTicker(PIXI.Ticker)

// 1. 外部传入参数
const props = defineProps({
  /** Live2D 模型主配置文件路径 */
  modelPath: {
    type: String,
    required: true,
    default: '/live2d/Haru/Haru.model3.json'
  },
  /** 模型缩放比例 */
  scale: {
    type: Number,
    default: 0.5
  },
  /** 模型水平偏移比例（0-1） */
  xRatio: {
    type: Number,
    default: 0.5
  }
})

// 2. 组件内部状态
const canvasRef = ref(null)
const app = ref(null)
const model = ref(null)
const isLoading = ref(false)
const loadError = ref('')

// 3. 定义可触发事件
const emit = defineEmits(['modelLoaded', 'loadFailed'])

// 4. 暴露给父组件的方法
defineExpose({
  /** 切换表情 */
  changeExpression: (type) => {
    if (!model.value) {
      ElMessage.warning('Live2D模型尚未加载完成，无法切换表情')
      return
    }
    try {
      model.value.expression(type)
      ElMessage.success(`已切换表情：${type}`)
    } catch (error) {
      ElMessage.error(`表情切换失败：${error.message}`)
      console.error('Live2D expression error:', error)
    }
  },
  /** 重新加载当前模型 */
  reloadModel: () => {
    loadModel(props.modelPath)
  }
})

// 5. 模型加载核心方法
const loadModel = async (modelPath) => {
  isLoading.value = true
  loadError.value = ''
  destroyModelAndApp()

  try {
    // ✅ 新增：获取父容器尺寸，限制PIXI画布最大尺寸
    const container = canvasRef.value.parentElement; // 获取.live2d-container
    const maxWidth = container.clientWidth; // 父容器宽度
    const maxHeight = container.clientHeight; // 父容器高度
    console.log('Container size:', maxWidth, maxHeight)

    app.value = new PIXI.Application({
      view: canvasRef.value,
      autoStart: true,
      backgroundAlpha: 0,
      width: maxWidth,
      height: maxHeight,
      resizeTo: container, // 跟随父容器缩放（关键）
      antialias: true,
      resolution: window.devicePixelRatio || 1
    })

    // 加载模型
    model.value = await Live2DModel.from(modelPath)
    app.value.stage.addChild(model.value)

    // 设置初始状态
    model.value.scale.set(props.scale)
    // // ✅ 优化模型缩放：确保模型完全在画布内
    const modelWidth = model.value.width;
    const modelHeight = model.value.height;
    // // 计算缩放比例（确保模型宽高不超过画布）
    const scaleX = maxWidth / modelWidth * 0.8; // 0.8是预留边距，避免贴边
    const scaleY = maxHeight / modelHeight * 0.8;
    const finalScale = Math.min(scaleX, scaleY, props.scale); // 取最小比例，不超过props设置的scale
    model.value.scale.set(finalScale);

    // 设置缩放（支持 X 和 Y 分别设置）
    console.log('scaleY：', scaleY)
    model.value.scale.y = scaleY            // 只缩放 Y 轴
    // console.log('props.xRatio：', props.xRatio)
    // const scaleX_final = app.value.renderer.width*0.5*props.xRatio  // 计算 X 轴缩放比例 ,0.6是预留边距，避免贴边
    // console.log('model x：', scaleX_final)
    // model.value.x = scaleX_final


    updateModelPosition()

    // 监听窗口大小变化
    window.addEventListener('resize', updateModelPosition)

    isLoading.value = false
    ElMessage.success('Live2D模型加载成功')
    emit('modelLoaded', model.value)

  } catch (error) {
    isLoading.value = false
    loadError.value = `模型加载失败：${error.message}`
    ElMessage.error(loadError.value)
    emit('loadFailed', error)
    console.error('Live2D load error:', error)
  }
}

// 6. 更新模型位置
// const updateModelPosition = () => {
//   if (!app.value || !model.value || !canvasRef.value) return
//   //const canvasWidth = canvasRef.value.offsetWidth
//   console.log('更新模型位置')
//   console.log('props.xRatio：', props.xRatio)
//   console.log('app.value.renderer.width：', app.value.renderer.width)
//   const scaleX_final = app.value.renderer.width*0.5*props.xRatio  // 计算 X 轴缩放比例 ,0.6是预留边距，避免贴边
//   console.log('model x：', scaleX_final)
//   model.value.x = scaleX_final

//   //model.value.x = canvasWidth * props.xRatio
// }

const updateModelPosition = () => {
  if (!app.value || !model.value) return // 无需依赖 canvasRef，用 PIXI 内部状态更可靠

  // 1. 获取 CSS 像素的舞台尺寸（PIXI 已处理好 DPR，直接用）
  const stageWidth = app.value.screen.width;  // 容器的 CSS 宽度（比如 800px）
  const stageHeight = app.value.screen.height; // 容器的 CSS 高度（比如 600px）

  // 2. 获取模型缩放后的实际宽高（原始宽高 × 缩放比例）
  const modelScaledWidth = model.value.width * model.value.scale.x;  // 缩放后模型宽度
  const modelScaledHeight = model.value.height * model.value.scale.y; // 缩放后模型高度

  // 3. 计算 X 轴位置：支持 xRatio 偏移，且保证模型不超出容器
  // 逻辑：(容器宽度 - 模型宽度) × xRatio → 0=最左，1=最右，0.5=居中
  const modelX = (stageWidth - modelScaledWidth) * props.xRatio * 0.7;
  // 防止 x 为负数（比如 xRatio 异常时）
  model.value.x = Math.max(0, modelX);

  // 4. 计算 Y 轴位置（可选：贴底部/居中，根据需求选一种）
  // 方案1：贴容器底部（聊天场景推荐，角色“站”在底部）
  const modelY = stageHeight - modelScaledHeight;
  // 方案2：垂直居中（通用场景）
  // const modelY = (stageHeight - modelScaledHeight) / 2;
  // 防止 y 为负数
  //model.value.y = Math.max(0, modelY);

  // 调试用：查看关键参数（可选删除）
  console.log('更新模型位置：');
  console.log('舞台尺寸（CSS像素）：', stageWidth, '×', stageHeight);
  console.log('模型实际尺寸：', modelScaledWidth, '×', modelScaledHeight);
  console.log('最终位置：x=', model.value.x, 'y=', model.value.y);
}



// 7. 资源销毁
const destroyModelAndApp = () => {
  if (model.value) {
    model.value.destroy()
    model.value = null
  }
  if (app.value) {
    app.value.destroy(true)
    app.value = null
  }
}

// 8. 生命周期
onMounted(() => {
  loadModel(props.modelPath)
})

onUnmounted(() => {
  destroyModelAndApp()
  window.removeEventListener('resize', updateModelPosition)
})

// 9. 监听模型路径变化
watch(
  () => props.modelPath,
  (newPath) => {
    if (newPath) loadModel(newPath)
  },
  { immediate: false }
)
</script>

<style scoped>
.live2d-container {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
}

.live2d-canvas {
  width: 100%;
  height: 100%;
  max-width: 100%; /* 禁止画布宽度超出父容器 */
  max-height: 100%; /* 禁止画布高度超出父容器 */
  display: block;
  object-fit: contain; /* 保持模型比例，避免拉伸 */
}

.live2d-loading,
.live2d-error {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 16px;
  padding: 12px 24px;
  border-radius: 8px;
  z-index: 10;
}

.live2d-loading {
  background-color: rgba(255, 255, 255, 0.8);
  color: #606266;
}

.live2d-error {
  background-color: rgba(255, 87, 34, 0.8);
  color: #fff;
}
</style>